#include "widget.h"
#include "ui_widget.h"
#include "spot.h"
#include <QDebug>
#include <QTimer>
#include <QElapsedTimer>

const int fps = 500;
const float maxSpeed = 200;

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    initSrcSpot();
    initDstSpot();
    initSimulator();

    initTimer_createrSpots();
    initTimer_updateSimulator();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::initSrcSpot()
{
    _src = new Spot(this);
    _src->setradius(20);
    _src->setpos({0, height() / 2});
    _src->setpainter([](QPainter& painter){
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setPen(QPen(Qt::blue, 3));
        painter.setBrush(Qt::NoBrush);
    });
}

void Widget::initDstSpot()
{
    _dst = new Spot(this);
    _dst->setradius(20);
    _dst->setpos({width(), height() / 2});
    _dst->setpainter([](QPainter& painter){
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setPen(QPen(Qt::red, 3));
        painter.setBrush(Qt::NoBrush);
    });
}

void Widget::initSimulator()
{
    _simulator = new RVO::RVOSimulator();
    _simulator->setAgentDefaults(25.0F, 10U, 1.5F, 1.5F, 10.0F, maxSpeed);
}

void Widget::initTimer_createrSpots()
{
    _timer_createrSpots = new QTimer(this);
    _timer_createrSpots->setTimerType(Qt::PreciseTimer); // 毫秒级, 不过还是会受时间片影响

    connect(_timer_createrSpots, &QTimer::timeout, this, [=](){
        RVO::Vector2 src(_src->getpos().x(), _src->getpos().y());
        Node* node = new Node;
        _nodes.append(node);
        // r, id, pos
        int r = node->r = 10;
        node->id = _simulator->addAgent(src, 2*r + 4, 10U, 1.5F, 1.5F, r, maxSpeed);
        node->pos = src;

        // 现有节点数
        ui->pushButton->setText("Units : " + QString::number(_nodes.size()));
    });
}

void Widget::initTimer_updateSimulator()
{
    _timer_updateSimulator = new QTimer(this);
    _timer_updateSimulator->setTimerType(Qt::PreciseTimer);
    connect(_timer_updateSimulator, &QTimer::timeout, this, &Widget::updateSimulator);
}

void Widget::changeEvent(QEvent *event)
{
    if (event->type() == QEvent::ActivationChange){
        if (!isActiveWindow()){
            qDebug() << "窗口失去焦点, 通知子控件...";
            _dst->focusout();
        }
    }

    QWidget::changeEvent(event);
}

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setBrush(Qt::NoBrush);
    painter.setPen(QPen(QColor("#C7C7C7"), 2));
    for(auto node : _nodes){
        painter.drawEllipse(QPointF(node->pos.x(), node->pos.y()), node->r - 2, node->r - 2);
    }
}

void Widget::updateSimulator()
{
    static QElapsedTimer eTimer;
    static bool first = true;

    if (first) {
        eTimer.start();
        first = false;
        return; // 第一帧跳过
    }

    // 使用真实经过的时间作为时间步长
    qint64 dt_ms_real = eTimer.restart();
    double dt_s_real = dt_ms_real * 0.001;

    double timeStep = std::min(dt_s_real, 1.0 / 15.0); // 最低15fps, 不过感觉用处不大?

    _simulator->setTimeStep(timeStep);



    static int count = 0;
    count++; // 实际执行次数
    static qint64 passedtime = 0;
    passedtime += dt_ms_real;
    if (passedtime >= 1000) {
        double fps = count * 1000.0 / passedtime;
        ui->pushButton_2->setText("FPS : " + QString::number(fps, 'f', 1));
        count = 0;
        passedtime = 0;
    }

    RVO::Vector2 dst(_dst->getpos().x(), _dst->getpos().y());
    for(int i = 0; i < _nodes.size(); ++i){
        _nodes[i]->pos = _simulator->getAgentPosition(i);
        RVO::Vector2 goalVector = dst - _nodes[i]->pos;

        if (RVO::absSq(goalVector) > 1.0f) {
            goalVector = RVO::normalize(goalVector);
        }

        _simulator->setAgentPrefVelocity(i, goalVector * maxSpeed);
    }
    _simulator->doStep();
    update();
}

void Widget::on_pushButton_clicked()
{
    qDebug() << " test btn ";
}

void Widget::on_pushButton_3_clicked()
{
    _timer_updateSimulator->start(1000 / fps);
    _timer_createrSpots->start(1000 / fps);
}

void Widget::on_pushButton_4_clicked()
{
    _timer_createrSpots->stop();
}

void Widget::on_pushButton_5_clicked()
{
    _timer_updateSimulator->start(1000 / fps);
}

void Widget::on_pushButton_6_clicked()
{
    _timer_createrSpots->stop();
    _timer_updateSimulator->stop();
}
